package com.xbongbong.paas.outerlink;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.outLink.domain.entity.OuterLinkConfigEntity;
import com.xbongbong.outLink.domain.entity.OuterLinkEntity;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EsAliasEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.VisibleRulePoJo;
import com.xbongbong.paas.form.AbstractFormService;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.model.OuterLinkConfigModel;
import com.xbongbong.paas.model.OuterLinkModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.OutLinkFieldAttrEntity;
import com.xbongbong.paas.pojo.OutLinkSubFormPojo;
import com.xbongbong.paas.pojo.dto.OuterLinkAddOutLinkExtensionDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkAdvancedGetDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkAdvancedSaveDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkAppearanceGetDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkAppearanceSaveDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkCloseOutLinkDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkConfigGetDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkDelOutLinkExtensionDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkDisplayGetDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkDisplaySaveDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkFilterGetDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkFilterSaveDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkGetOutLinkExtensionDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkPermissionGetDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkPermissionSaveDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.OuterTokenUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.outerlink.interfaces.PaasOuterLinkConfigService;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.errorcodes.OutLinkErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.outLink.pojo.OutLinkAdvancedGetVO;
import com.xbongbong.pro.outLink.pojo.OutLinkDeleteVO;
import com.xbongbong.pro.outLink.pojo.OutLinkDisplayGetVO;
import com.xbongbong.pro.outLink.pojo.OutLinkExtensionAddVO;
import com.xbongbong.pro.outLink.pojo.OutLinkExtensionGetVO;
import com.xbongbong.pro.outLink.pojo.OutLinkFilterGetVO;
import com.xbongbong.pro.outLink.pojo.OutLinkPermissonGetVO;
import com.xbongbong.pro.outLink.pojo.OutLinkSettingGetVO;
import com.xbongbong.pro.outLink.pojo.OuterLinkAppearanceGetVO;
import com.xbongbong.pro.outLink.pojo.OuterLinkShareVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderTemplateEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.ForbiddenSettingEnum;
import com.xbongbong.saas.enums.OutLinkSettingTypeEnum;
import com.xbongbong.saas.enums.OuterLinkTypeEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.model.WorkOrderTemplateModel;
import com.xbongbong.saas.script.help.SaasInitExplainsHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 外链设置抽象类
 * @author zheng.li
 **/
@Slf4j
@Component
public abstract class AbstractPaasOuterLinkConfigService extends AbstractFormService implements PaasOuterLinkConfigService{


    private static final List<Integer> FILTER_ATTR = Arrays.asList(FieldTypeEnum.TEXT.getType(), FieldTypeEnum.NUM.getType(), FieldTypeEnum.DATETIME.getType(),
            FieldTypeEnum.RADIO_GROUP.getType(), FieldTypeEnum.COMBO.getType(), FieldTypeEnum.ADDRESS.getType(), FieldTypeEnum.SERIALNO.getType(), FieldTypeEnum.COMBO_CHECK.getType(), FieldTypeEnum.LABEL.getType());

    // 外链拓展目前最多拓展20个
    private static final int OUTLINK_EXTENSION_MAX = 20;

    @Resource
    private OuterLinkConfigModel outerLinkConfigModel;
    @Resource
    private OuterLinkModel outerLinkModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private WorkOrderTemplateModel workOrderTemplateModel;
    @Resource
    private PackageHelp packageHelp;



    @Override
    public OuterLinkAppearanceGetVO getAppearance(OuterLinkAppearanceGetDTO outerLinkAppearanceGetDTO) throws XbbException {
        OuterLinkAppearanceGetVO outerLinkAppearanceGetVO = new OuterLinkAppearanceGetVO();

        Long formId = outerLinkAppearanceGetDTO.getFormId();
        String corpid = outerLinkAppearanceGetDTO.getCorpid();
        Integer type = OuterLinkTypeEnum.WRITE.getCode();

        OuterLinkConfigEntity appearanceConfigEntity = getOuterLinkConfigEntities(corpid, formId, type, OutLinkSettingTypeEnum.APPEARANCE_SETTING.getCode());
        if (Objects.isNull(appearanceConfigEntity)) {
            JSONObject configInfo = new JSONObject();
            // 背景图片
            configInfo.put("bgUrl", "");
            // 背景颜色
            configInfo.put("bgColor", "rgba(255,255,255,1)");
            // 字体大小
            configInfo.put("fontSize", 28);
            // 字体颜色
            configInfo.put("fontColor", "rgba(0,0,0,1)");
            // 字体位置  11：左上 12：中上 13：右上  21：左中  22：居中  23：右中  31：左下  32：中下  33：右下
            configInfo.put("position", 11);
            outerLinkAppearanceGetVO.setConfigInfo(configInfo);
            outerLinkAppearanceGetVO.setThemeList(new JSONArray());
            outerLinkAppearanceGetVO.setThemeList(new JSONArray());
            outerLinkAppearanceGetVO.setInitFlag(BasicConstant.ZERO);
        } else {
            JSONObject templateInfo = appearanceConfigEntity.getTemplateInfo();
            JSONObject configInfo = templateInfo.getJSONObject("configInfo");
            outerLinkAppearanceGetVO.setConfigInfo(configInfo);

            JSONArray themeList = templateInfo.getJSONArray("themeList");
            outerLinkAppearanceGetVO.setThemeList(themeList);
            outerLinkAppearanceGetVO.setInitFlag(BasicConstant.ONE);
        }
        return outerLinkAppearanceGetVO;
    }

    @Override
    public BaseVO saveAppearance(OuterLinkAppearanceSaveDTO outerLinkAppearanceSaveDTO) throws XbbException {
        Long formId = outerLinkAppearanceSaveDTO.getFormId();
        String corpid = outerLinkAppearanceSaveDTO.getCorpid();
        Integer type = OuterLinkTypeEnum.WRITE.getCode();

        JSONArray themeList = outerLinkAppearanceSaveDTO.getThemeList();
        JSONObject configInfo = outerLinkAppearanceSaveDTO.getConfigInfo();

        JSONObject templateInfo = new JSONObject();
        OuterLinkConfigEntity appearanceConfigEntity = getOuterLinkConfigEntities(corpid, formId, type, OutLinkSettingTypeEnum.APPEARANCE_SETTING.getCode());
        try {
            if (Objects.isNull(appearanceConfigEntity)) {
                appearanceConfigEntity = new OuterLinkConfigEntity();
                appearanceConfigEntity.setType(type);
                appearanceConfigEntity.setFormId(formId);
                appearanceConfigEntity.setCorpid(corpid);
                appearanceConfigEntity.setDel(DelEnum.NORMAL.getDel());
                appearanceConfigEntity.setConfigType(OutLinkSettingTypeEnum.APPEARANCE_SETTING.getCode());

                templateInfo.put("themeList", themeList);
                templateInfo.put("configInfo", configInfo);
                appearanceConfigEntity.setTemplateInfo(templateInfo);
            } else {
                templateInfo.put("themeList", themeList);
                templateInfo.put("configInfo", configInfo);
                appearanceConfigEntity.setTemplateInfo(templateInfo);
            }
            outerLinkConfigModel.save(appearanceConfigEntity);
        } catch (XbbException e) {
            log.error("保存外链外观设置失败" + e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return new BaseVO();
    }

    /**
     * 获取权限设置
     *
     * @param outerLinkPermissionGetDTO
     * @return
     * @throws XbbException
     */
    @Override
    public BaseVO getPermission(OuterLinkPermissionGetDTO outerLinkPermissionGetDTO) throws XbbException {
        OutLinkPermissonGetVO outLinkPermissonGetVO = new OutLinkPermissonGetVO();

        Integer businessType = outerLinkPermissionGetDTO.getBusinessType();
        Long formId = outerLinkPermissionGetDTO.getFormId();
        String corpid = outerLinkPermissionGetDTO.getCorpid();
        Integer type = outerLinkPermissionGetDTO.getType();

        List<FieldAttrEntity> filteredSpecialAttr = getOutLinkFieldList(corpid, formId, businessType, type, null);
        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, type, OutLinkSettingTypeEnum.PERMISSION_SETTING.getCode());

        if (Objects.isNull(outerLinkConfigEntity)) {
            List<OutLinkFieldAttrEntity> explains = new ArrayList<>();
            for (int i = 0; i < filteredSpecialAttr.size(); i++) {
                FieldAttrEntity fieldAttrEntity = filteredSpecialAttr.get(i);
                OutLinkFieldAttrEntity outLinkFieldAttrEntity = new OutLinkFieldAttrEntity(fieldAttrEntity.getFieldType(), fieldAttrEntity.getAttrName(), fieldAttrEntity.getAttr(), fieldAttrEntity.getAttrName(), 1, 1, 1, 0);
                if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                    // 外链分享默认可见不可编辑
                    outLinkFieldAttrEntity.setEditable(BasicConstant.ZERO);
                }
                if (ExplainUtil.isSubFormNoSelectProduct(fieldAttrEntity.getFieldType())) {
                    // 子表单
                    if (Objects.isNull(fieldAttrEntity.getSubForm())) {
                        continue;
                    }
                    List<FieldAttrEntity> subExplainList = JSONObject.parseArray(JSON.toJSONString(fieldAttrEntity.getSubForm().getItems()), FieldAttrEntity.class);
                    List<OutLinkFieldAttrEntity> subFormFieldAttrList = new ArrayList<>();
                    if (Objects.nonNull(subExplainList)) {
                        subExplainList.forEach(item -> {
                            OutLinkFieldAttrEntity subOutLinkFieldAttrEntity = new OutLinkFieldAttrEntity(item.getFieldType(), item.getAttrName(), item.getAttr(), item.getAttrName(), 1, 1, 1, 0);
                            if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                                // 外链分享默认可见不可编辑
                                subOutLinkFieldAttrEntity.setEditable(BasicConstant.ZERO);
                            }
                            subFormFieldAttrList.add(subOutLinkFieldAttrEntity);
                        });
                    }
                    OutLinkSubFormPojo subFormPoJo = new OutLinkSubFormPojo();
                    subFormPoJo.setItems(subFormFieldAttrList);
                    outLinkFieldAttrEntity.setSubForm(subFormPoJo);
                }
                explains.add(outLinkFieldAttrEntity);
            }
            outLinkPermissonGetVO.setExplainList(explains);
        } else {
            List<OutLinkFieldAttrEntity> outLinkFieldAttrEntityList = JSONArray.parseArray(outerLinkConfigEntity.getExplains(), OutLinkFieldAttrEntity.class);
            outLinkFieldAttrEntityList = syncOuterLinkField(filteredSpecialAttr, outLinkFieldAttrEntityList, OuterLinkTypeEnum.getByCode(type), OutLinkSettingTypeEnum.PERMISSION_SETTING);
            outLinkPermissonGetVO.setExplainList(outLinkFieldAttrEntityList);
        }
        return outLinkPermissonGetVO;
    }

    /**
     * 同步解释 包括新增和删除的解释
     *
     * @param filteredSpecialAttr
     * @param outLinkFieldAttrEntityList
     * @return
     */
    @Override
    public List<OutLinkFieldAttrEntity> syncOuterLinkField(List<FieldAttrEntity> filteredSpecialAttr, List<OutLinkFieldAttrEntity> outLinkFieldAttrEntityList, OuterLinkTypeEnum type, OutLinkSettingTypeEnum configType) {
        Map<String, OutLinkFieldAttrEntity> outLinkExplainMap = new HashMap<>(filteredSpecialAttr.size());
        outLinkFieldAttrEntityList.forEach((item) -> {
            outLinkExplainMap.put(item.getAttr(), item);
        });
        List<OutLinkFieldAttrEntity> newOuterLinkAttrs = new ArrayList<>(outLinkFieldAttrEntityList.size());
        Integer defaultEditable = 1;
        Integer defaultVisiable = 1;
        Integer defaultFilterable = 1;
        Integer defaultRename = 0;
        if (Objects.equals(type, OuterLinkTypeEnum.SHARE)) {
            defaultEditable = 0;
        }
        for (FieldAttrEntity fieldAttrEntity : filteredSpecialAttr) {
            String attr = fieldAttrEntity.getAttr();
            Integer fieldType = fieldAttrEntity.getFieldType();
            String attrName = fieldAttrEntity.getAttrName();
            OutLinkFieldAttrEntity outLinkFieldAttrEntity = outLinkExplainMap.get(attr);
            if (Objects.isNull(outLinkFieldAttrEntity) ||
                    (ExplainUtil.isSubFormNoSelectProduct(outLinkFieldAttrEntity.getFieldType()) && outLinkFieldAttrEntity.getSubForm() == null)
            ) {
                outLinkFieldAttrEntity = new OutLinkFieldAttrEntity(fieldType, attrName, attr, attrName, defaultEditable, defaultVisiable, defaultFilterable, defaultRename);
                if (ExplainUtil.isSubFormNoSelectProduct(fieldAttrEntity.getFieldType())) {
                    // 子表单
                    if (Objects.isNull(fieldAttrEntity.getSubForm())) {
                        continue;
                    }
                    List<FieldAttrEntity> subExplainList = JSONObject.parseArray(JSON.toJSONString(fieldAttrEntity.getSubForm().getItems()), FieldAttrEntity.class);
                    List<OutLinkFieldAttrEntity> subFormFieldAttrList = new ArrayList<>();
                    if (Objects.nonNull(subExplainList)) {
                        subExplainList.forEach(item -> {
                            OutLinkFieldAttrEntity subOutLinkFieldAttrEntity = new OutLinkFieldAttrEntity(item.getFieldType(), item.getAttrName(), item.getAttr(), item.getAttrName(), 1, 1, 1, 0);
                            if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                                // 外链分享默认可见不可编辑
                                subOutLinkFieldAttrEntity.setEditable(BasicConstant.ZERO);
                            }
                            subFormFieldAttrList.add(subOutLinkFieldAttrEntity);
                        });
                    }
                    OutLinkSubFormPojo subFormPoJo = new OutLinkSubFormPojo();
                    subFormPoJo.setItems(subFormFieldAttrList);
                    outLinkFieldAttrEntity.setSubForm(subFormPoJo);
                }
            } else {
                outLinkFieldAttrEntity.setAttrName(fieldAttrEntity.getAttrName());
                if (!Objects.equals(configType, OutLinkSettingTypeEnum.DISPLAY_SETTING.getCode())) {
                    // 外链显示设置这里，defaultName是用设置里配置的值处理的，其它的值只要用表单的值作为展示就行了
                    outLinkFieldAttrEntity.setDefaultName(fieldAttrEntity.getAttrName());
                }
                if (ExplainUtil.isSubFormNoSelectProduct(fieldAttrEntity.getFieldType())) {
                    if (outLinkFieldAttrEntity.getSubForm() == null || fieldAttrEntity.getSubForm() == null) {
                        continue;
                    }
                    List<? extends OutLinkFieldAttrEntity> outerLinkItems = outLinkFieldAttrEntity.getSubForm().getItems();
                    Map<String, OutLinkFieldAttrEntity> subItemsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    if (CollectionsUtil.isNotEmpty(outerLinkItems)) {
                        outerLinkItems.forEach(item -> subItemsMap.put(item.getAttr(), item));
                    }
                    List<? extends FieldAttrEntity> items = fieldAttrEntity.getSubForm().getItems();
                    if (CollectionsUtil.isNotEmpty(items)) {
                        List<OutLinkFieldAttrEntity> subItem = new ArrayList<>();
                        for (FieldAttrEntity item : items) {
                            String subAttr = item.getAttr();
                            String subAttrName = item.getAttrName();
                            OutLinkFieldAttrEntity subOuterLinkField = subItemsMap.get(subAttr);
                            if (Objects.isNull(subOuterLinkField)) {
                                subOuterLinkField = new OutLinkFieldAttrEntity(item.getFieldType(), subAttrName, subAttr, subAttrName, defaultEditable, defaultVisiable, defaultFilterable, defaultRename);
                            } else {
                                subOuterLinkField.setAttrName(subAttrName);
                                if (!Objects.equals(configType, OutLinkSettingTypeEnum.DISPLAY_SETTING.getCode())) {
                                    // 外链显示设置这里，defaultName是用设置里配置的值处理的，其它的值只要用表单的值作为展示就行了
                                    subOuterLinkField.setDefaultName(subAttrName);
                                }
                            }
                            subItem.add(subOuterLinkField);
                        }
                        outLinkFieldAttrEntity.getSubForm().setItems(subItem);
                    }
                }
            }
            newOuterLinkAttrs.add(outLinkFieldAttrEntity);
        }
        return newOuterLinkAttrs;
    }

    /**
     * 权限设置保存
     *
     * @param outerLinkPermissionSaveDTO
     * @return
     * @throws XbbException
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseVO permissionSave(OuterLinkPermissionSaveDTO outerLinkPermissionSaveDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        Integer type = outerLinkPermissionSaveDTO.getType();
        String corpid = outerLinkPermissionSaveDTO.getCorpid();
        Long formId = outerLinkPermissionSaveDTO.getFormId();

        List<OutLinkFieldAttrEntity> explainList = outerLinkPermissionSaveDTO.getExplainList();
        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, type, OutLinkSettingTypeEnum.PERMISSION_SETTING.getCode());
        try {
            if (Objects.isNull(outerLinkConfigEntity)) {
                OuterLinkConfigEntity entity = new OuterLinkConfigEntity();
                entity.setConfigType(1);
                entity.setCorpid(corpid);
                entity.setDel(0);
                entity.setFormId(formId);
                entity.setDefaultFormName("");
                entity.setType(type);
                entity.setExplains(JSONArray.toJSONString(explainList));
                entity.setSeniorInfo(new JSONObject());
                entity.setTemplateInfo(new JSONObject());
                outerLinkConfigModel.insert(entity);
            } else {
                outerLinkConfigEntity.setExplains(JSONArray.toJSONString(explainList));
                outerLinkConfigModel.update(outerLinkConfigEntity);
            }
        } catch (Exception e) {
            log.error("权限更新失败" + e);
            throw new XbbException(ErrorCodeEnum.API_FAIL);
        }
        return baseVO;
    }

    /**
     * 显示设置保存
     *
     * @param outerLinkDisplaySaveDTO
     * @return
     * @throws XbbException
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseVO displaySave(OuterLinkDisplaySaveDTO outerLinkDisplaySaveDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        Integer businessType = outerLinkDisplaySaveDTO.getBusinessType();
        String corpid = outerLinkDisplaySaveDTO.getCorpid();
        Long formId = outerLinkDisplaySaveDTO.getFormId();
        Integer type = outerLinkDisplaySaveDTO.getType();
        List<OutLinkFieldAttrEntity> frontFieldList = outerLinkDisplaySaveDTO.getDisplayFields();
        Map<String, String> renamedMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, String> renamedSubMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (int i = 0; i < frontFieldList.size(); i++) {
            OutLinkFieldAttrEntity item = frontFieldList.get(i);
            renamedMap.put(item.getAttr(), item.getDefaultName());
            if (Objects.equals(item.getFieldType(), FieldTypeEnum.SUB_FORM.getType())
                    || Objects.equals(item.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType())) {
                List<OutLinkFieldAttrEntity> subExplainList = JSONObject.parseArray(JSON.toJSONString(item.getSubForm().getItems()), OutLinkFieldAttrEntity.class);
                if (Objects.nonNull(subExplainList)) {
                    for (int j = 0; j < subExplainList.size(); j++) {
                        OutLinkFieldAttrEntity entity = subExplainList.get(j);
                        renamedSubMap.put(item.getAttr() + "." + entity.getAttr(), entity.getDefaultName());
                    }
                }
            }
        }
        frontFieldList.forEach(item -> renamedMap.put(item.getAttr(), item.getDefaultName()));

        String defaultFormName = outerLinkDisplaySaveDTO.getDefaultFormName();

        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, OuterLinkTypeEnum.getByCode(type).getCode(), OutLinkSettingTypeEnum.DISPLAY_SETTING.getCode());
        List<FieldAttrEntity> filteredSpecialAttr = getOutLinkFieldList(corpid, formId, businessType, type, null);
        List<OutLinkFieldAttrEntity> explains = new ArrayList<>();
        for (int i = 0; i < filteredSpecialAttr.size(); i++) {
            FieldAttrEntity item = filteredSpecialAttr.get(i);
            String attr = item.getAttr();
            OutLinkFieldAttrEntity outLinkFieldAttrEntity = new OutLinkFieldAttrEntity(item.getFieldType(), item.getAttrName(), attr, Objects.isNull(renamedMap.get(attr)) ? item.getAttrName() : renamedMap.get(attr), 1, 1, 1, Objects.isNull(renamedMap.get(attr)) ? 0 : 1);
            if (Objects.equals(item.getFieldType(), FieldTypeEnum.SUB_FORM.getType())
                    || Objects.equals(item.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType())) {
                // 子表单
                List<? extends FieldAttrEntity> subExplainList = item.getSubForm().getItems();
                List<OutLinkFieldAttrEntity> subFormFieldAttrList = new ArrayList<>();
                if (Objects.nonNull(subExplainList)) {
                    subExplainList.forEach(it -> {
                        OutLinkFieldAttrEntity subOutLinkFieldAttrEntity = new OutLinkFieldAttrEntity(it.getFieldType(), it.getAttrName(), it.getAttr(), Objects.isNull(renamedSubMap.get(attr + "." + it.getAttr())) ? it.getAttrName() : renamedSubMap.get(attr + "." + it.getAttr()), 1, 1, 1, Objects.isNull(renamedSubMap.get(attr + "." + it.getAttr())) ? 0 : 1);
                        subFormFieldAttrList.add(subOutLinkFieldAttrEntity);
                    });
                }
                OutLinkSubFormPojo subFormPoJo = new OutLinkSubFormPojo();
                subFormPoJo.setItems(subFormFieldAttrList);
                outLinkFieldAttrEntity.setSubForm(subFormPoJo);
            }
            explains.add(outLinkFieldAttrEntity);
        }
        try {
            if (Objects.isNull(outerLinkConfigEntity)) {
                OuterLinkConfigEntity entity = new OuterLinkConfigEntity();
                entity.setConfigType(OutLinkSettingTypeEnum.DISPLAY_SETTING.getCode());
                entity.setCorpid(corpid);
                entity.setDel(DelEnum.NORMAL.getDel());
                entity.setFormId(formId);
                entity.setDefaultFormName(defaultFormName);
                entity.setType(type);
                entity.setExplains(JSONArray.toJSONString(explains));
                entity.setSeniorInfo(new JSONObject());
                entity.setTemplateInfo(new JSONObject());
                outerLinkConfigModel.insert(entity);
            } else {
                outerLinkConfigEntity.setExplains(JSONArray.toJSONString(explains));
                outerLinkConfigEntity.setDefaultFormName(defaultFormName);
                outerLinkConfigModel.update(outerLinkConfigEntity);
            }
        } catch (Exception e) {
            log.error("筛选更新失败" + e);
            throw new XbbException(ErrorCodeEnum.API_FAIL);
        }
        return baseVO;
    }


    /**
     * 表单外链设置获取
     *
     * @param outerLinkConfigGetDTO
     * @return
     * @throws XbbException
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OutLinkSettingGetVO getOutLinkConfig(OuterLinkConfigGetDTO outerLinkConfigGetDTO) throws XbbException {
        OutLinkSettingGetVO outLinkSettingGetVO = new OutLinkSettingGetVO();
        Integer businessType = outerLinkConfigGetDTO.getBusinessType();
        String corpid = outerLinkConfigGetDTO.getCorpid();
        Long formId = outerLinkConfigGetDTO.getFormId();
        Integer isGet = outerLinkConfigGetDTO.getIsGet();

        List<Integer> enableList = outerLinkConfigGetDTO.getEnableList();
        JSONObject formAdd = new JSONObject();
        formAdd.put("enable", 0);
        formAdd.put("url", "");
        JSONObject formQuery = new JSONObject();
        formQuery.put("enable", 0);
        formQuery.put("url", "");
        JSONObject formShare = new JSONObject();
        formShare.put("enable", 0);
        formShare.put("url", "");
        // 已经有的记录 排除拓展字段
        List<OuterLinkEntity> outerLinkEntityList = getOuterLinkEntitiesExcludeExpandField(corpid, formId, null, null, null);
        List<Integer> alreadyGenerate = new ArrayList<>();
        if (Objects.nonNull(outerLinkEntityList)) {
            for (int i = 0; i < outerLinkEntityList.size(); i++) {
                OuterLinkEntity item = outerLinkEntityList.get(i);
                Integer type = item.getType();
                Integer enable = item.getEnable();
                String token = item.getHashCode();
                String url = proBaseConfig.getWebFrontUrl() + "outer-form.html#/" + token;
                alreadyGenerate.add(type);
                if (Objects.equals(type, OuterLinkTypeEnum.WRITE.getCode())) {
                    formAdd.put("enable", enable);
                    formAdd.put("url", url + "1");
                } else if (Objects.equals(type, OuterLinkTypeEnum.SEARCH.getCode())) {
                    formQuery.put("enable", enable);
                    formQuery.put("url", url + "2");
                } else if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                    formShare.put("enable", enable);
                }
            }
        }
        if (Objects.equals(isGet, 0)) {
            // 开启链接

            if (CollectionsUtil.isNotEmpty(enableList)) {
                Integer type = enableList.get(0);
                List<OuterLinkEntity> outerLinks = getOuterLinkEntitiesExcludeExpandField(corpid, formId, type, null, null);
                String url = null;
                if (CollectionsUtil.isNotEmpty(outerLinks)) {
                    for (int i = 0; i < outerLinks.size(); i++) {
                        OuterLinkEntity outerLinkEntity = outerLinks.get(i);
                        outerLinkEntity.setEnable(1);
                        String token = outerLinkEntity.getHashCode();
                        url = proBaseConfig.getWebFrontUrl() + "outer-form.html#/" + token;
                        outerLinkModel.update(outerLinkEntity);
                    }
                }
                if (Objects.equals(type, OuterLinkTypeEnum.WRITE.getCode())) {
                    formAdd.put("enable", 1);
                    formAdd.put("url", url + "1");
                } else if (Objects.equals(type, OuterLinkTypeEnum.SEARCH.getCode())) {
                    formQuery.put("enable", 1);
                    formQuery.put("url", url + "2");
                } else if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                    formShare.put("enable", 1);
                }
            }
            // 生成链接
            enableList.removeAll(alreadyGenerate);
            for (int i = 0; i < enableList.size(); i++) {
                Integer type = enableList.get(i);
                String token = OuterTokenUtil.getEncryptToken(formId, corpid, businessType, type, "");
                String url = proBaseConfig.getWebFrontUrl() + "outer-form.html#/" + token;
                OuterLinkEntity outerLinkEntity = new OuterLinkEntity();
                outerLinkEntity.setCorpid(corpid);
                outerLinkEntity.setFormId(formId);
                outerLinkEntity.setBusinessType(businessType);
                outerLinkEntity.setDel(0);
                outerLinkEntity.setEnable(1);
                if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                    // 外链分享需要用到dataId,所以默认为0
                    outerLinkEntity.setDataId(0L);
                }
                outerLinkEntity.setHashCode(token);
                outerLinkEntity.setType(type);
                outerLinkEntity.setBusinessType(businessType);
                outerLinkModel.insert(outerLinkEntity);
                if (Objects.equals(type, OuterLinkTypeEnum.WRITE.getCode())) {
                    formAdd.put("enable", 1);
                    formAdd.put("url", url + "1");
                } else if (Objects.equals(type, OuterLinkTypeEnum.SEARCH.getCode())) {
                    formQuery.put("enable", 1);
                    formQuery.put("url", url + "2");
                } else if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                    formShare.put("enable", 1);
                }
            }

        }
        outLinkSettingGetVO.setFormId(formId);
        outLinkSettingGetVO.setFormAdd(formAdd);
        outLinkSettingGetVO.setFormQuery(formQuery);
        outLinkSettingGetVO.setFormShare(formShare);
        notSupportOutLink(outLinkSettingGetVO, businessType, outerLinkConfigGetDTO);
        return outLinkSettingGetVO;
    }

    /**
     * 暂不支持外链的表单
     *
     * @param outLinkSettingGetVO
     * @param businessType
     */
    private void notSupportOutLink(OutLinkSettingGetVO outLinkSettingGetVO, Integer businessType, OuterLinkConfigGetDTO outerLinkConfigGetDTO) throws XbbException {
        // 不支持外链填写的业务
        List<Integer> notSupportOutLinkAdd = Arrays.asList(XbbRefTypeEnum.PAYMENT.getCode(),
                XbbRefTypeEnum.PAY_PLAN.getCode(),
                XbbRefTypeEnum.CONTRACT.getCode(),
                XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(),
                XbbRefTypeEnum.COMMUNICATE_PLAN.getCode(),
                XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode(),
                XbbRefTypeEnum.QUOTATION.getCode(),
                XbbRefTypeEnum.REFUND.getCode(),
                XbbRefTypeEnum.WORK_REPORT.getCode(),
                XbbRefTypeEnum.WORKREPORT_DAILY.getCode(),
                XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode(),
                XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode(),
                XbbRefTypeEnum.SUPPLIER_CONTACT.getCode(),
                XbbRefTypeEnum.SUPPLIER_COMMUNICATE.getCode(),
                XbbRefTypeEnum.SUPPLIER.getCode(),
                XbbRefTypeEnum.RETURNED_PURCHASE.getCode(),
                XbbRefTypeEnum.BOM_BILL.getCode(),
                XbbRefTypeEnum.PRODUCTION_ORDER.getCode(),
                XbbRefTypeEnum.INVENTORY.getCode(),
                XbbRefTypeEnum.WAREHOUSE.getCode(),
                XbbRefTypeEnum.ASSEMBLE.getCode(),
                XbbRefTypeEnum.TRANSFER.getCode(),
                XbbRefTypeEnum.PURCHASE_INSTOCK.getCode(),
                XbbRefTypeEnum.REFUND_INSTOCK.getCode(),
                XbbRefTypeEnum.OTHER_INSTOCK.getCode(),
                XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode(),
                XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode(),
                XbbRefTypeEnum.OUTSTOCK.getCode(),
                XbbRefTypeEnum.OTHER_OUTSTOCK.getCode(),
                XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(),
                XbbRefTypeEnum.RETURNED_PURCHASE_OUTSTOCK.getCode(),
                XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode(),
                XbbRefTypeEnum.WORK_ORDER_OUTSTOCK.getCode(),
                XbbRefTypeEnum.PAYMENT_SHEET.getCode(),
                XbbRefTypeEnum.PURCHASE_INVOICE.getCode(),
                XbbRefTypeEnum.PURCHASE.getCode(),
                XbbRefTypeEnum.PAY_SHEET.getCode(),
                XbbRefTypeEnum.CONTACT.getCode(),
                XbbRefTypeEnum.INVOICE.getCode(),
                XbbRefTypeEnum.PRODUCT.getCode(),
                XbbRefTypeEnum.RECEIPT_ORDER.getCode(),
                XbbRefTypeEnum.SERVICE_PROJECT.getCode(),
                XbbRefTypeEnum.SIGNIN.getCode()
        );
        // 不支持外链查询的业务 客户，合同，联系人
        List<Integer> notSupportOutLinkQuery = Arrays.asList(
                XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(),
                XbbRefTypeEnum.CONTRACT.getCode(),
                XbbRefTypeEnum.SIGNIN.getCode(),
                XbbRefTypeEnum.CONTACT.getCode());

        // 不支持外链分享的业务 签到
        List<Integer> notSupportOutLinkShare = Arrays.asList(
                XbbRefTypeEnum.SIGNIN.getCode());

        outLinkSettingGetVO.getFormAdd().put("show", true);
        outLinkSettingGetVO.getFormQuery().put("show", true);
        outLinkSettingGetVO.getFormShare().put("show", true);

        if (notSupportOutLinkAdd.contains(businessType)) {
            outLinkSettingGetVO.getFormAdd().put("show", false);
        }
        if (notSupportOutLinkQuery.contains(businessType)) {
            outLinkSettingGetVO.getFormQuery().put("show", false);
        }
        if (notSupportOutLinkShare.contains(businessType)) {
            outLinkSettingGetVO.getFormShare().put("show", false);
        }
        // 特殊处理工单
        if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
            boolean isFree;
            WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(outerLinkConfigGetDTO.getFormId(), outerLinkConfigGetDTO.getCorpid());
            if (workOrderExplainEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            WorkOrderFormEntityExt workOrderEntity = workOrderFormModel.getByKey(outerLinkConfigGetDTO.getFormId(), outerLinkConfigGetDTO.getCorpid());
            WorkOrderTemplateEntity workOrderTemplateEntity = workOrderTemplateModel.getBykey(workOrderEntity.getTemplateId(), outerLinkConfigGetDTO.getCorpid());
            isFree = Objects.equals(workOrderTemplateEntity.getIsFree(), 1);
            if (isFree) {
                outLinkSettingGetVO.getFormAdd().put("show", false);
            }
        }
    }

    /**
     * 筛选设置保存
     *
     * @param outerLinkFilterSaveDTO
     * @return
     * @throws XbbException
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseVO filterSave(OuterLinkFilterSaveDTO outerLinkFilterSaveDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        List<String> screenList = outerLinkFilterSaveDTO.getScreenList();
        Integer businessType = outerLinkFilterSaveDTO.getBusinessType();
        String corpid = outerLinkFilterSaveDTO.getCorpid();
        Long formId = outerLinkFilterSaveDTO.getFormId();
        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, OuterLinkTypeEnum.SEARCH.getCode(), OutLinkSettingTypeEnum.FILTER_SETTING.getCode());
        List<FieldAttrEntity> filteredSpecialAttr = getOutLinkFieldList(corpid, formId, businessType, OuterLinkTypeEnum.SEARCH.getCode(), BasicConstant.ONE);

        List<OutLinkFieldAttrEntity> explains = new ArrayList<>();
        for (int i = 0; i < filteredSpecialAttr.size(); i++) {
            FieldAttrEntity item = filteredSpecialAttr.get(i);
            OutLinkFieldAttrEntity outLinkFieldAttrEntity = new OutLinkFieldAttrEntity(item.getFieldType(), item.getAttrName(), item.getAttr(), item.getAttrName(), 1, 1, 1, 0);
            if (!screenList.contains(item.getAttr())) {
                outLinkFieldAttrEntity.setFilterable(0);
            }
            explains.add(outLinkFieldAttrEntity);
        }
        try {
            if (Objects.isNull(outerLinkConfigEntity)) {
                OuterLinkConfigEntity entity = new OuterLinkConfigEntity();
                entity.setConfigType(OutLinkSettingTypeEnum.FILTER_SETTING.getCode());
                entity.setCorpid(corpid);
                entity.setDel(DelEnum.NORMAL.getDel());
                entity.setFormId(formId);
                entity.setDefaultFormName("");
                entity.setType(OuterLinkTypeEnum.SEARCH.getCode());
                entity.setExplains(JSONArray.toJSONString(explains));
                entity.setSeniorInfo(new JSONObject());
                entity.setTemplateInfo(new JSONObject());
                outerLinkConfigModel.insert(entity);
            } else {
                outerLinkConfigEntity.setExplains(JSONArray.toJSONString(explains));
                outerLinkConfigModel.update(outerLinkConfigEntity);
            }
        } catch (Exception e) {
            log.error("筛选更新失败" + e);
            throw new XbbException(ErrorCodeEnum.API_FAIL);
        }
        return baseVO;
    }

    /**
     * 高级设置保存
     *
     * @param outerLinkAdvancedSaveDTO
     * @return
     * @throws XbbException
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseVO advancedSave(OuterLinkAdvancedSaveDTO outerLinkAdvancedSaveDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        Integer businessType = outerLinkAdvancedSaveDTO.getBusinessType();
        Long formId = outerLinkAdvancedSaveDTO.getFormId();
        String corpid = outerLinkAdvancedSaveDTO.getCorpid();
        JSONObject seniorInfoPojo = outerLinkAdvancedSaveDTO.getSetting();
        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, OuterLinkTypeEnum.WRITE.getCode(), OutLinkSettingTypeEnum.ADVANCED_SETTING.getCode());
        try {
            if (Objects.isNull(outerLinkConfigEntity)) {
                OuterLinkConfigEntity entity = new OuterLinkConfigEntity();
                entity.setDefaultFormName("");
                entity.setTemplateInfo(new JSONObject());
                entity.setType(OuterLinkTypeEnum.WRITE.getCode());
                entity.setConfigType(OutLinkSettingTypeEnum.ADVANCED_SETTING.getCode());
                entity.setSeniorInfo(seniorInfoPojo);
                entity.setExplains("");
                entity.setFormId(formId);
                entity.setCorpid(corpid);
                outerLinkConfigModel.insert(entity);
            } else {
                outerLinkConfigEntity.setSeniorInfo(seniorInfoPojo);
                outerLinkConfigModel.update(outerLinkConfigEntity);
            }
        } catch (Exception e) {
            log.error("高级设置更新失败", e);
            throw new XbbException(ErrorCodeEnum.API_FAIL);
        }

        return baseVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public OuterLinkShareVO shareCopy(OuterLinkDTO outerLinkDTO) throws XbbException {
        OuterLinkShareVO outerLinkShareVO = new OuterLinkShareVO();
        Integer businessType = outerLinkDTO.getBusinessType();
        String corpid = outerLinkDTO.getCorpid();
        Long formId;
        Long dataId = outerLinkDTO.getDataId();
        //校验套餐类型
        Integer feeType = packageHelp.getFeeType(corpid);
        if (Objects.equals(feeType, PackageTypeEnum.STANDARD.getType())) {
            throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405014);
        }
        if (Objects.isNull(dataId)) {
            throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405004);
        }
        Integer type = OuterLinkTypeEnum.SHARE.getCode();

        PaasFormDataEntityExt paasFormDataEntityExt = getFormData(dataId,corpid,businessType);

        if (Objects.isNull(paasFormDataEntityExt)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }

        formId = paasFormDataEntityExt.getFormId();
        OuterLinkEntity outerLink = outerLinkModel.getOuterLink(formId, type, corpid, 0L);
        if (Objects.nonNull(outerLink)) {
            if (!Objects.equals(outerLink.getEnable(), BasicConstant.ONE)) {
                throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405003);
            }
        } else {
            throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405003);
        }

        if (Objects.equals(businessType, XbbRefTypeEnum.WORK_REPORT.getCode())) {
            // 工作报告的businessType前端传来2101，没有具体到日、周、月，所以这里手动转一下
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("formId", formId);
            List<PaasFormEntityExt> entitys = paasFormModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(entitys)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
            }
            businessType = entitys.get(0).getBusinessType();
        }

        String createrId = "";
        if (Objects.nonNull(paasFormDataEntityExt)) {
            createrId = paasFormDataEntityExt.getCreatorId();
        }
        String token = "";
        OuterLinkEntity outerLinkEntity = outerLinkModel.getOuterLink(formId, type, corpid, dataId);
        if (Objects.nonNull(outerLinkEntity)) {
            token = outerLinkEntity.getHashCode();
        } else {
            try {
                token = OuterTokenUtil.getEncryptToken(formId, corpid, businessType, type, dataId, createrId);
                outerLinkEntity = new OuterLinkEntity();
                outerLinkEntity.setCorpid(corpid);
                outerLinkEntity.setFormId(formId);
                outerLinkEntity.setDel(0);
                outerLinkEntity.setEnable(1);
                outerLinkEntity.setHashCode(token);
                outerLinkEntity.setDataId(dataId);
                outerLinkEntity.setType(type);
                outerLinkEntity.setBusinessType(businessType);
                outerLinkModel.insert(outerLinkEntity);
            } catch (XbbException e) {
                log.error("OuterLinkConfigServiceImpl.shareCopy失败:原因" + e.getMsg());
                throw new XbbException(ErrorCodeEnum.API_FAIL);
            }
        }
        String url = proBaseConfig.getWebFrontUrl() + "outer-form.html#/" + token + "3";
        outerLinkShareVO.setUrl(url);
        return outerLinkShareVO;
    }

    @Override
    public BaseVO closeOutLink(OuterLinkCloseOutLinkDTO outerLinkCloseOutLinkDTO) throws XbbException {
        OutLinkDeleteVO outLinkDeleteVO = new OutLinkDeleteVO();
        Integer businessType = outerLinkCloseOutLinkDTO.getBusinessType();
        Long formId = outerLinkCloseOutLinkDTO.getFormId();
        String corpid = outerLinkCloseOutLinkDTO.getCorpid();
        Integer type = outerLinkCloseOutLinkDTO.getDisable();
//        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid,formId, type,null);
        List<OuterLinkEntity> OuterLinkEntities = getOuterLinkEntities(corpid, formId, type, null, null, DelEnum.NORMAL.getDel());
        if (CollectionsUtil.isNotEmpty(OuterLinkEntities)) {
            try {
                for (int i = 0; i < OuterLinkEntities.size(); i++) {
                    OuterLinkEntity outerLinkEntity = OuterLinkEntities.get(i);
                    outerLinkEntity.setEnable(0);
                    outerLinkModel.update(outerLinkEntity);
                }
            } catch (Exception e) {
                log.error("关闭外链出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            return outLinkDeleteVO;
        }
        return null;
    }

    /**
     * 添加外链拓展字段
     *
     * @param outerLinkAddOutLinkExtensionDTO
     * @return
     * @throws XbbException
     */
    @Override
    public OutLinkExtensionAddVO addOutLinkExtension(OuterLinkAddOutLinkExtensionDTO outerLinkAddOutLinkExtensionDTO) throws XbbException {
        OutLinkExtensionAddVO outLinkExtensionAddVO = new OutLinkExtensionAddVO();
        JSONObject extension = new JSONObject();
        Integer businessType = outerLinkAddOutLinkExtensionDTO.getBusinessType();
        String corpid = outerLinkAddOutLinkExtensionDTO.getCorpid();
        Long formId = outerLinkAddOutLinkExtensionDTO.getFormId();
        String extenedField = outerLinkAddOutLinkExtensionDTO.getExtenedField();
        Integer type = OuterLinkTypeEnum.WRITE.getCode();

        // 外链删除与否不影响
        String extensionAttr = null;
        // 之前有没有拓展过
        boolean flag = false;

        // 目前已经拓展了多少个外链 已经删除的外链不计入其内
        int count = 0;
        // 是否有重复的外链值 比如两个抖音
        boolean repeat = false;

        List<OuterLinkEntity> outerLinkEntityList = getOuterLinkEntities(corpid, formId, OuterLinkTypeEnum.WRITE.getCode(), null, null, DelEnum.NORMAL.getDel());
        if (CollectionsUtil.isNotEmpty(outerLinkEntityList)) {
            for (int i = 0; i < outerLinkEntityList.size(); i++) {
                OuterLinkEntity outerLinkEntity = outerLinkEntityList.get(i);
                if (Objects.equals(outerLinkEntity.getExpandField(), extenedField)) {
                    repeat = true;
                }
                if (Objects.isNull(outerLinkEntity.getAttr())) {
                    continue;
                }
                count++;
            }
        }

        List<OuterLinkEntity> outerLinkEntities = getOuterLinkEntities(corpid, formId, OuterLinkTypeEnum.WRITE.getCode(), null, null, null);
        if (CollectionsUtil.isNotEmpty(outerLinkEntities)) {
            for (int i = 0; i < outerLinkEntities.size(); i++) {
                OuterLinkEntity outerLink = outerLinkEntities.get(i);
                if (Objects.isNull(outerLink.getAttr())) {
                    continue;
                }
                flag = true;
                extensionAttr = outerLink.getAttr();
            }
        }

        if (count >= OUTLINK_EXTENSION_MAX) {
            throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405011);
        }
        if (repeat) {
            throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405012);
        }
        if (StringUtil.isNotEmpty(extenedField) && extenedField.length() > 20) {
            throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405013);
        }
        if (flag) {
            // attr 若outlinkyouattr直接用 没有动态生成
            try {
                String token = OuterTokenUtil.getEncryptToken(formId, corpid, businessType, type, extenedField);
                String url = proBaseConfig.getWebFrontUrl() + "outer-form.html#/" + token + "1";
                OuterLinkEntity outerLinkEntity = new OuterLinkEntity();
                outerLinkEntity.setCorpid(corpid);
                outerLinkEntity.setFormId(formId);
                outerLinkEntity.setBusinessType(businessType);
                outerLinkEntity.setDel(0);
                outerLinkEntity.setEnable(1);
                outerLinkEntity.setAttr(extensionAttr);
                if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                    // 外链分享需要用到dataId,所以默认为0
                    outerLinkEntity.setDataId(0L);
                }
                outerLinkEntity.setHashCode(token);
                outerLinkEntity.setType(type);
                outerLinkEntity.setBusinessType(businessType);
                outerLinkEntity.setExpandField(extenedField);
                outerLinkModel.insert(outerLinkEntity);
                extension.put("field", extenedField);
                extension.put("url", url);
                extension.put("id", outerLinkEntity.getId());
                outLinkExtensionAddVO.setExtension(extension);
            } catch (Exception e) {
                log.error("添加外链拓展失败", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        } else {
            // 获取拓展字段的attr并outlink插一条记录 attr
            PaasFormExplainEntity paasFormExplainEntity = getFormExplain(corpid,formId,businessType);
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            // 有没有空位 如果有空位可以存放 则返回true 没有空位可以存放 则返回false
            boolean hasEmpty = false;
            for (int i = 1; i <= EsAliasEnum.TEXT.getSaasMax(); i++) {
                // text_i有没有被占用
                boolean occupation = false;
                for (int j = 0; j < explainList.size(); j++) {
                    FieldAttrEntity fieldAttrEntity = explainList.get(j);
                    if (("text_" + i).equals(fieldAttrEntity.getAttr())) {
                        occupation = true;
                    }
                }
                if (occupation) {
                    continue;
                } else {
                    hasEmpty = true;
                    extensionAttr = "text_" + i;
                    break;
                }
            }
            if (!hasEmpty) {
                throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405008);
            }
            FieldAttrEntity fieldAttrEntity = SaasInitExplainsHelper.getNewFieldAttrEntity();
            fieldAttrEntity.setAttr(extensionAttr);
            fieldAttrEntity.setAttrName(I18nMessageUtil.getMessage(I18nStringConstant.OUT_EXTENSION));
            fieldAttrEntity.setFieldType(FieldTypeEnum.TEXT.getType());
            fieldAttrEntity.setVisible(1);
            fieldAttrEntity.setSaasAttr("extensionField");
            fieldAttrEntity.setEditable(0);
            fieldAttrEntity.setShowType(ShowTypeEnum.LIST_DETAIL.getCode());
            fieldAttrEntity.setShowRemove(0);
            fieldAttrEntity.setIsForbidden(1);
            fieldAttrEntity.setIsRedundant(0);
            fieldAttrEntity.setShowEditable(0);
            fieldAttrEntity.setSort(explainList.size());
            fieldAttrEntity.setVisibleScopeRule(new VisibleRulePoJo());
            fieldAttrEntity.setAttrType(FieldTypeEnum.TEXT.getEsalias());
            fieldAttrEntity.setForbiddenSettingList(Arrays.asList(ForbiddenSettingEnum.DISABLE_DEFAULT.getAlias(), ForbiddenSettingEnum.DISABLE_RULE.getAlias(), ForbiddenSettingEnum.DISABLE_TYPE.getAlias()));
            explainList.add(fieldAttrEntity);
            paasFormExplainEntity.setExplains(JSONObject.toJSONString(explainList));
            if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
                //工单
                WorkOrderExplainEntity workOrderExplainEntity = new WorkOrderExplainEntity();
                BeanUtil.copyProperties(paasFormExplainEntity, workOrderExplainEntity);
                workOrderExplainModel.update(workOrderExplainEntity);
            } else {
                // 其他
                paasFormExplainModel.update(paasFormExplainEntity);
            }

            // 拓展字段重复

            try {
                String token = OuterTokenUtil.getEncryptToken(formId, corpid, businessType, type, extenedField);
                String url = proBaseConfig.getWebFrontUrl() + "outer-form.html#/" + token + "1";
                OuterLinkEntity outerLinkEntity = new OuterLinkEntity();
                outerLinkEntity.setCorpid(corpid);
                outerLinkEntity.setFormId(formId);
                outerLinkEntity.setBusinessType(businessType);
                outerLinkEntity.setDel(0);
                outerLinkEntity.setEnable(1);
                outerLinkEntity.setAttr(extensionAttr);
                if (Objects.equals(type, OuterLinkTypeEnum.SHARE.getCode())) {
                    // 外链分享需要用到dataId,所以默认为0
                    outerLinkEntity.setDataId(0L);
                }
                outerLinkEntity.setHashCode(token);
                outerLinkEntity.setType(type);
                outerLinkEntity.setBusinessType(businessType);
                outerLinkEntity.setExpandField(extenedField);
                outerLinkModel.insert(outerLinkEntity);
                extension.put("field", extenedField);
                extension.put("url", url);
                extension.put("id", outerLinkEntity.getId());
                outLinkExtensionAddVO.setExtension(extension);
            } catch (Exception e) {
                log.error("添加外链拓展失败", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
        }

        return outLinkExtensionAddVO;
    }

    /**
     * 删除外链拓展字段
     *
     * @param outerLinkDelOutLinkExtensionDTO
     * @return
     * @throws XbbException
     */
    @Override
    public BaseVO delOutLinkExtension(OuterLinkDelOutLinkExtensionDTO outerLinkDelOutLinkExtensionDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        Long id = outerLinkDelOutLinkExtensionDTO.getId();
        try {
            outerLinkModel.deleteByKey(id);
        } catch (Exception e) {
            log.error("删除拓展链接 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return baseVO;
    }

    @Override
    public OutLinkExtensionGetVO getOutLinkExtension(OuterLinkGetOutLinkExtensionDTO outerLinkGetOutLinkExtensionDTO) throws XbbException {
        OutLinkExtensionGetVO outLinkExtensionGetVO = new OutLinkExtensionGetVO();
        JSONArray extension = new JSONArray();
        Long formId = outerLinkGetOutLinkExtensionDTO.getFormId();
        String corpid = outerLinkGetOutLinkExtensionDTO.getCorpid();
        Integer businessType = outerLinkGetOutLinkExtensionDTO.getBusinessType();
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("type", OuterLinkTypeEnum.WRITE.getCode());
        params.put("del", 0);
        params.put("formId", formId);
        params.put("corpid", corpid);
        params.put("businessType", businessType);
        List<OuterLinkEntity> outerLinkEntityList = outerLinkModel.findEntitys(params);
        if (CollectionsUtil.isNotEmpty(outerLinkEntityList)) {
            for (int i = 0; i < outerLinkEntityList.size(); i++) {
                OuterLinkEntity outerLinkEntity = outerLinkEntityList.get(i);
                if (StringUtil.isEmpty(outerLinkEntity.getExpandField())) {
                    continue;
                }
                String token = outerLinkEntity.getHashCode();
                String url = proBaseConfig.getWebFrontUrl() + "outer-form.html#/" + token + "1";
                JSONObject extensionJSON = new JSONObject();
                extensionJSON.put("id", outerLinkEntity.getId());
                extensionJSON.put("field", outerLinkEntity.getExpandField());
                extensionJSON.put("url", url);
                extension.add(extensionJSON);
            }
        }
        outLinkExtensionGetVO.setExtension(extension);
        return outLinkExtensionGetVO;
    }

    /**
     * 高级设置获取
     *
     * @param outerLinkAdvancedGetDTO
     * @return
     * @throws XbbException
     */
    @Override
    public OutLinkAdvancedGetVO getAdvanced(OuterLinkAdvancedGetDTO outerLinkAdvancedGetDTO) throws XbbException {
        OutLinkAdvancedGetVO outLinkAdvancedGetVO = new OutLinkAdvancedGetVO();
        Long formId = outerLinkAdvancedGetDTO.getFormId();
        String corpid = outerLinkAdvancedGetDTO.getCorpid();
        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, OuterLinkTypeEnum.WRITE.getCode(), OutLinkSettingTypeEnum.ADVANCED_SETTING.getCode());
        JSONObject limit = new JSONObject();
        limit.put("enable", false);
        JSONObject openCloseTime = new JSONObject();
        openCloseTime.put("enable", false);
        if (Objects.nonNull(outerLinkConfigEntity)) {
            JSONObject jsonObject = outerLinkConfigEntity.getSeniorInfo();
            limit = jsonObject.getJSONObject("limit");
            openCloseTime = jsonObject.getJSONObject("openCloseTime");
        }
        outLinkAdvancedGetVO.setLimit(limit);
        outLinkAdvancedGetVO.setOpenCloseTime(openCloseTime);
        return outLinkAdvancedGetVO;
    }

    @Override
    public OutLinkDisplayGetVO displayGet(OuterLinkDisplayGetDTO outerLinkDisplayGetDTO) throws XbbException {
        OutLinkDisplayGetVO outLinkDisplayGetVO = new OutLinkDisplayGetVO();
        Integer businessType = outerLinkDisplayGetDTO.getBusinessType();
        String corpid = outerLinkDisplayGetDTO.getCorpid();
        Long formId = outerLinkDisplayGetDTO.getFormId();
        Integer type = outerLinkDisplayGetDTO.getType();
        List<OutLinkFieldAttrEntity> displayFields = new ArrayList<>();

        PaasFormEntity paasFormEntity = this.getForm(corpid,formId,businessType);
        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, OuterLinkTypeEnum.getByCode(type).getCode(), OutLinkSettingTypeEnum.DISPLAY_SETTING.getCode());
        List<FieldAttrEntity> filteredSpecialAttr = getOutLinkFieldList(corpid, formId, businessType, type, null);

        outLinkDisplayGetVO.setExplainList(filteredSpecialAttr);
        if (Objects.isNull(outerLinkConfigEntity)) {
            outLinkDisplayGetVO.setFormName(paasFormEntity.getName());
            outLinkDisplayGetVO.setDefaultFormName(paasFormEntity.getName());
        } else {
            outLinkDisplayGetVO.setFormName(paasFormEntity.getName());
            outLinkDisplayGetVO.setDefaultFormName(outerLinkConfigEntity.getDefaultFormName());

            List<OutLinkFieldAttrEntity> list = JSONArray.parseArray(outerLinkConfigEntity.getExplains(), OutLinkFieldAttrEntity.class);
            for (int i = 0; i < list.size(); i++) {
                OutLinkFieldAttrEntity outLinkFieldAttrEntity = list.get(i);
                Integer renamed = outLinkFieldAttrEntity.getRenamed();

                if (Objects.equals(renamed, 1)) {
                    if (Objects.equals(outLinkFieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())
                            || Objects.equals(outLinkFieldAttrEntity.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType())) {
                        // 子表单
                        List<? extends OutLinkFieldAttrEntity> subExplainList = outLinkFieldAttrEntity.getSubForm().getItems();
                        List<OutLinkFieldAttrEntity> subFormFieldAttrList = new ArrayList<>();
                        if (Objects.nonNull(subExplainList)) {
                            subExplainList.forEach(item -> {
                                if (Objects.equals(item.getRenamed(), 1)) {
                                    subFormFieldAttrList.add(item);
                                }
                            });
                        }
                        OutLinkSubFormPojo subFormPoJo = new OutLinkSubFormPojo();
                        subFormPoJo.setItems(subFormFieldAttrList);
                        outLinkFieldAttrEntity.setSubForm(subFormPoJo);
                    }
                    displayFields.add(outLinkFieldAttrEntity);
                }
            }
        }
        outLinkDisplayGetVO.setDisplayFields(displayFields);
        return outLinkDisplayGetVO;
    }


    /**
     * 获取外链设置
     *
     * @param corpid
     * @param formId
     * @param type
     * @param configType
     * @return
     * @throws XbbException
     */
    @Override
    public OuterLinkConfigEntity getOuterLinkConfigEntities(String corpid, Long formId, Integer type, Integer configType) throws XbbException {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("type", type);
        params.put("corpid", corpid);
        params.put("del", DelEnum.NORMAL.getDel());
        params.put("formId", formId);
        params.put("configType", configType);
        List<OuterLinkConfigEntity> entityList = outerLinkConfigModel.findEntitys(params);
        if (CollectionsUtil.isNotEmpty(entityList)) {
            return entityList.get(0);
        }
        return null;
    }

    private List<OuterLinkEntity> getOuterLinkEntities(String corpid, Long formId, Integer type, Long dataId, String extenedField, Integer del) throws XbbException {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", corpid);
        params.put("del", del);
        params.put("formId", formId);
        params.put("type", type);
        params.put("dataId", dataId);
        params.put("expandField", extenedField);
        List<OuterLinkEntity> entityList = outerLinkModel.findEntitys(params);
        if (CollectionsUtil.isNotEmpty(entityList)) {
            return entityList;
        }
        return null;
    }

    private List<OuterLinkEntity> getOuterLinkEntitiesExcludeExpandField(String corpid, Long formId, Integer type, Long dataId, String extenedField) throws XbbException {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", corpid);
        params.put("del", DelEnum.NORMAL.getDel());
        params.put("formId", formId);
        params.put("type", type);
        params.put("dataId", dataId);
        params.put("excludeExpandField", "excludeExpandField");
        List<OuterLinkEntity> entityList = outerLinkModel.findEntitys(params);
        if (CollectionsUtil.isNotEmpty(entityList)) {
            return entityList;
        }
        return null;
    }

    /**
     * 获取外链筛选项设置
     *
     * @param outerLinkFilterGetDTO
     * @return
     * @throws XbbException
     */
    @Override
    public OutLinkFilterGetVO filterGet(OuterLinkFilterGetDTO outerLinkFilterGetDTO) throws XbbException {
        OutLinkFilterGetVO outLinkFilterGetVO = new OutLinkFilterGetVO();
        List<String> screen = new ArrayList<>();

        Integer businessType = outerLinkFilterGetDTO.getBusinessType();
        Long formId = outerLinkFilterGetDTO.getFormId();
        String corpid = outerLinkFilterGetDTO.getCorpid();
        List<FieldAttrEntity> filteredSpecialAttr = getOutLinkFieldList(corpid, formId, businessType, OuterLinkTypeEnum.SEARCH.getCode(), BasicConstant.ONE);

        OuterLinkConfigEntity outerLinkConfigEntity = getOuterLinkConfigEntities(corpid, formId, OuterLinkTypeEnum.SEARCH.getCode(), OutLinkSettingTypeEnum.FILTER_SETTING.getCode());
        if (Objects.isNull(outerLinkConfigEntity)) {
            for (int i = 0; i < filteredSpecialAttr.size(); i++) {
                screen.add(filteredSpecialAttr.get(i).getAttr());
            }

        } else {
            List<OutLinkFieldAttrEntity> list = JSONArray.parseArray(outerLinkConfigEntity.getExplains(), OutLinkFieldAttrEntity.class);
            list = syncOuterLinkField(filteredSpecialAttr, list, OuterLinkTypeEnum.SEARCH, OutLinkSettingTypeEnum.FILTER_SETTING);
            for (int i = 0; i < list.size(); i++) {
                if (Objects.equals(list.get(i).getFilterable(), 1)) {
                    screen.add(list.get(i).getAttr());
                }
            }
        }
        outLinkFilterGetVO.setFormExplainList(filteredSpecialAttr);
        outLinkFilterGetVO.setScreen(screen);
        return outLinkFilterGetVO;
    }



    @Override
    public List<FieldAttrEntity> getOutLinkFieldList(String corpid, Long formId, Integer businessType, Integer type, Integer fromFilter) throws XbbException {
        // 获取表单解释
        PaasFormExplainEntity paasFormExplainEntity = getFormExplain(corpid,formId,businessType);
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        if (Objects.equals(type, OuterLinkTypeEnum.SEARCH.getCode()) && Objects.equals(fromFilter, BasicConstant.ONE)) {
            // 外链筛选仅支持单行文本、数字、日期、单选按钮、下拉框、地址、流水号、标签
            explainList.removeIf(item -> !FILTER_ATTR.contains(item.getFieldType()));
            explainList.removeIf(item -> !ShowTypeEnum.listShow(item.getShowType()));
            explainList.removeIf(item -> Objects.equals("extensionField", item.getSaasAttr()));
            explainList.removeIf(item -> Objects.equals(item.getIsOpen(), 2));
            return explainList;
        }
        ExplainUtil.filterSpecialAttr(explainList, type, null);
        OuterLinkTypeEnum typeEnum = OuterLinkTypeEnum.getByCode(type);
        // 去除不支持的字段
        removeUnsupportedAttr(businessType,explainList,typeEnum);

        return explainList;
    }


}

